package com.fido.kingkongview

import android.content.Context
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.ViewTreeObserver
import android.widget.LinearLayout
import androidx.cardview.widget.CardView
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.fido.kingkongview.holder.KHolderCreator
import com.fido.kingkongview.indicator.KIndicatorCreator
import com.fido.kingkongview.indicator.KingKongIndicator
import com.fido.kingkongview.utils.HandleDataUtils
import com.fido.kingkongview.utils.height
import com.fido.kingkongview.utils.margin
import com.fido.kingkongview.utils.scrollPercent
import com.fido.kingkongview.utils.smoothScrollToPositionWithCustomSpeed
import com.fido.kingkongview.view.KingKongFlingRecyclerView
import kotlin.math.abs
import kotlin.math.max


/**
 * @author: FiDo
 * @date: 2024/7/24
 * @des:
 */
class KingKongView<T> @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null
) : LinearLayout(context, attrs) {

    companion object {
        private const val TAG = "KingKongView"
        
        /**
         * 仿淘宝样式的真正行数
         * [setUp]时设置lines，可以通过该函数获取矫正后行数
         */
        fun <T> fakeAliRealLines(list: List<T?>?, spanCount: Int): Int {
            val notNullSize = list?.filterNot { it == null }?.size ?: 0
            var lines = 1
            if (notNullSize > 0) {
                lines =
                    if ((notNullSize - spanCount) % spanCount == 0) (notNullSize - spanCount) / spanCount else (notNullSize - spanCount) / spanCount + 1
            }
            return lines
        }
    }

    private lateinit var recyclerView: KingKongFlingRecyclerView
    private lateinit var layoutManager: GridLayoutManager
    private lateinit var rvContainer: CardView
    private var lines = 1  //最大显示行数
    private var spanCount = 4 //一屏显示的item数量，会影响item宽度
    private var offScreenItemWidth = 0 // >0时，额外显示一个item 距离屏幕右边的距离

    private var rvAdapter: KingKongItemAdapter<T>? = null

    private var mStyle: KingKongStyle = KingKongStyle.FAKE_ALI

    private var mDataList: List<T?>? = null

    private var pagingMode = true //是否将数据处理为分页模式，true时会将数据重新排序

    private var turningThreshold = 1 / 3.0 //翻页阙值,默认滑动1/3时翻译

    private var indicatorView: KingKongIndicator? = null //底部指示器

    init {
        initView()
        initEvent()
    }

    private fun initView() {
        orientation = VERTICAL
        layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
        gravity = Gravity.CENTER_HORIZONTAL

        rvContainer = CardView(context)
        rvContainer.layoutParams =
            LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
        rvContainer.cardElevation = 0f
        rvContainer.radius = 0f
        rvContainer.useCompatPadding = false

        recyclerView = KingKongFlingRecyclerView(context)
        recyclerView.apply {
            layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
            overScrollMode = View.OVER_SCROLL_NEVER
            isNestedScrollingEnabled = false
            setHasFixedSize(true)
        }
        layoutManager = GridLayoutManager(context, lines, GridLayoutManager.HORIZONTAL, false)
        recyclerView.layoutManager = layoutManager
        //adapter
        rvAdapter = KingKongItemAdapter(recyclerView)
        recyclerView.adapter = rvAdapter

        recyclerView.viewTreeObserver.addOnGlobalLayoutListener(object :
            ViewTreeObserver.OnGlobalLayoutListener {
            override fun onGlobalLayout() {
                recyclerView.viewTreeObserver.removeOnGlobalLayoutListener(this)
                rvAdapter?.onWidthChange(recyclerView.width)
            }
        })

        rvContainer.addView(recyclerView)

        addView(rvContainer)
        //add scrollIndicator
        indicatorView = KingKongIndicator(context = context, attrs = null)
        this.addView(indicatorView)
    }

    fun setTurningThreshold(threshold: Double) = apply {
        this.turningThreshold = threshold
    }

    /**
     * @param list 数据源
     * @param style [KingKongStyle]
     * @param lines 显示行数
     * @param span  显示列数
     * @param itemOffScreenWidth 额外显示的item宽度
     * @param itemClick 点击事件
     * @param holderCreator 创建ItemHolder函数
     */
    fun setUp(
        list: List<T?>?,
        style: KingKongStyle,
        lines: Int = this.lines,
        span: Int = this.spanCount,
        itemOffScreenWidth: Int = 0,
        itemClick: ((data: T?,pos:Int) -> Unit)? = null,
        holderCreator: KHolderCreator<T>
    ) {
        if (list.isNullOrEmpty()) return
        mDataList = list
        mStyle = style
        offScreenItemWidth = itemOffScreenWidth
        spanCount = span
        recyclerView.normalFling = true
        when (style) {
            KingKongStyle.ONE_LINE -> {
                this.lines = 1
                resetListParams()
            }

            KingKongStyle.MULTI_LINE -> {
                this.lines = lines
                //根据数据源动态调整lines
                fixLinesCount()
                fixData(mDataList ?: emptyList())
                resetListParams()
            }

            KingKongStyle.FAKE_ALI -> {
                this.lines = lines
                //将第一页数据进行填充
                fillNullData4FirstPage()
                pagingMode = true
                fixData(mDataList ?: emptyList())
                //开启触摸加速
                recyclerView.normalFling = false
            }
        }
        layoutManager.spanCount = this.lines
        showIndicator(
            ((mDataList?.size)
                ?: 0) > if (style == KingKongStyle.MULTI_LINE) this.lines * spanCount else spanCount
        )
        rvAdapter?.apply {
            setHolderCreator(holderCreator)
            setSpanCount(spanCount)
            if (itemClick != null) {
                setOnItemClickListener(itemClick)
            }
            setOffScreenWidth(offScreenItemWidth)

            setData(mDataList)

            resetListStatus()
        }
    }

    private fun resetListStatus() {
        dynamicItemMargin = 0
        lastDynamicItemMargin = 0
        if (mStyle == KingKongStyle.FAKE_ALI) {
            recyclerView.smoothScrollToPosition(0)
            recyclerView.post {
                rvAdapter?.updateItemHeight(oneItemHeight)
            }
        } else {
            recyclerView.scrollToPosition(0)
        }
        for (position in 0 until (mDataList?.size ?: 0)) {
            val itemView = layoutManager.findViewByPosition(position)
            itemView?.margin(leftMargin = dynamicItemMargin, rightMargin = dynamicItemMargin)
        }
    }

    private fun showIndicator(show: Boolean) {
        indicatorView?.visibility = if (show) View.VISIBLE else View.GONE
        if (show) {
            setupIndicator(style = mStyle)
        }
    }

    /**
     * @param indicatorWidth            指示器宽度
     * @param indicatorHeight           指示器高度
     * @param indicatorRadius           指示器圆角
     * @param indicatorBgColor          指示器背景色
     * @param indicatorThumbColor       指示器内部滑块颜色
     * @param indicatorThumbWidth       指示器内部滑块宽度
     * @param indicatorMarginTop        指示器离列表顶部距离
     * @param smallIndicatorHorizonGap  style==FakeAli时底部两个指示器间距
     * @param indicatorCreator          提供 draw方法，绘制自定义indicator
     */
    fun setupIndicator(
        style: KingKongStyle?=null,
        indicatorWidth: Int = 0,
        indicatorHeight: Int = 0,
        indicatorRadius: Int = 0,
        indicatorBgColor: Int = 0,
        indicatorThumbColor: Int = 0,
        indicatorThumbWidth: Int = 0,
        indicatorMarginTop: Int = 0,
        smallIndicatorHorizonGap: Int = 0,
        indicatorCreator: KIndicatorCreator? = null,
    ) {
        indicatorView?.apply {
            if (indicatorMarginTop > 0) {
                margin(topMargin = indicatorMarginTop)
            }
            setParams(
                indicatorWidth,
                indicatorHeight,
                indicatorRadius,
                indicatorBgColor,
                indicatorThumbColor,
                indicatorThumbWidth,
                smallIndicatorHorizonGap,
                indicatorCreator
            )
            mStyle = style ?: this@KingKongView.mStyle
        }
    }

    /**
     * 设置列表的触摸加速，默认时4.0 越大越快
     */
    fun setListFlingVelocity(flingVelocity: Double) {
        if (flingVelocity > 0) {
            recyclerView.setFlingVelocity(flingVelocity)
        }
    }

    //切换为单/多行 样式时 重置 CardView 高度,并将Rv重新滑动最左侧
    private fun resetListParams() {
        rvContainer.layoutParams =
            LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
    }

    private fun fillNullData4FirstPage() {
        if (mDataList.isNullOrEmpty()) return
        val allDataSize = lines * spanCount * 2
        val originalList = mDataList!!.toMutableList()
        if (mDataList!!.size < allDataSize) {
            for (i in 0 until (lines - 1) * spanCount) {
                originalList.add(spanCount, null)
            }
        }
        mDataList = originalList
    }

    private fun fixData(data: List<T?>) {
        if (pagingMode) {
            this.mDataList = HandleDataUtils.rearrange(data, this.lines, this.spanCount)
        } else {
            fillData(data)
        }
    }

    private fun fixLinesCount() {
        //如果总数据少于一页，动态调整行数
        val size = mDataList?.size ?: 0
        if (size <= spanCount * lines) {
            lines = if (size % spanCount == 0) size / spanCount else size / spanCount + 1
            lines = if (lines > 0) lines else 1
            layoutManager.spanCount = lines
        }
    }

    /**
     * 不排序时如果数据大于一页，使用空数据填满最后一列，用于修复滚动条滑动时变长变短的问题
     * @param data
     */
    private fun fillData(data: List<T?>) {
        if (lines <= 1) return
        mDataList = ArrayList<T?>(data)
        if (!mDataList.isNullOrEmpty()) {
            if (mDataList!!.size > lines * spanCount && mDataList!!.size % lines > 0) {
                val rest = lines - mDataList!!.size % lines
                for (i in 0 until rest) {
                    (mDataList as? ArrayList<T?>)?.add(null)
                }
            }
        }
    }

    private fun initEvent() {
        recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)

                indicatorView?.scrollListener?.onScrollStateChanged(recyclerView, newState)

                if (mStyle == KingKongStyle.FAKE_ALI) {
                    if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                        handleScroll(recyclerView)
                    }
                }
            }

            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)

                indicatorView?.scrollListener?.onScrolled(recyclerView, dx, dy)

                if (mStyle == KingKongStyle.FAKE_ALI) {
                    calculateItemHeightBasedOnScroll()
                    setNextPageItemMargin()
                }
            }
        })
    }

    private fun handleScroll(recyclerView: RecyclerView) {
        val targetPosition = if (recyclerView.scrollPercent > abs(turningThreshold)) {
            recyclerView.adapter?.itemCount?.minus(1) ?: 0
        } else {
            0
        }
        recyclerView.smoothScrollToPositionWithCustomSpeed(targetPosition)
    }

    private var lastDynamicItemMargin = 0
    private fun setNextPageItemMargin() {
        if (offScreenItemWidth > 0 && dynamicItemMargin > 0) {
            val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
            val lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition()
            for (position in firstVisibleItemPosition..lastVisibleItemPosition) {
                val itemView = layoutManager.findViewByPosition(position)
                if (itemView != null) {
                    val margin = max(lastDynamicItemMargin, dynamicItemMargin)
                    if (dynamicItemMargin > lastDynamicItemMargin) {
                        lastDynamicItemMargin = dynamicItemMargin
                    }
                    if (lastDynamicItemMargin == dynamicItemMargin) {
                        lastDynamicItemMargin = 0
                    }
//                    val colum = position / spanCount
                    //左右margin
//                    val leftMargin = if (colum==0) 0 else margin/2
//                    val rightMargin = if (colum==(spanCount-1)) 0 else margin/2
//                    itemView.margin(leftMargin = leftMargin, rightMargin = rightMargin )
                    itemView.margin(leftMargin = margin)
                }
            }
        }
    }

    private var oneItemHeight: Int = 0
        get() =
            if (field > 0) {
                field
            } else {
                var height = 0
                if (!mDataList.isNullOrEmpty()) {
                    val item = layoutManager.findViewByPosition(0)
                    height = item?.height ?: 0
                    rvAdapter?.updateItemHeight(height)
                }
                if (height > 0) {
                    field = height
                }
                field
            }

    private var dynamicItemMargin = 0 //当显示超屏item时，动态设置第二页的item margin,因为需要将第二页span沾满
    private fun calculateItemHeightBasedOnScroll() {
        val scrollPercent = recyclerView.scrollPercent

        if (offScreenItemWidth > 0) {
            dynamicItemMargin = ((offScreenItemWidth / spanCount) * scrollPercent).toInt()
        }
        if (scrollPercent == 0f) {
            rvContainer.height(oneItemHeight)
        } else {
            val dynamicHeight = ((oneItemHeight * lines) * scrollPercent).toInt()
            if (dynamicHeight >= oneItemHeight) {
                rvContainer.height(dynamicHeight)
            }
        }
    }
}

enum class KingKongStyle {
    ONE_LINE,  //只显示单行
    FAKE_ALI,  //仿淘宝
    MULTI_LINE, //多行
}
